/**
* Created with CLion.
* User:Lenovo
* Date:2023-03-20
* Time:18:55
* Description:功能模块
*/

#include "contacts.h"
int CheckCapacity(Contact *pc);

//静态版本
/*
void InitContact(Contact *pc)
{
    pc -> sz = 0;
    memset(pc -> data, 0, sizeof(pc -> data));
}
*/

void loadContact(Contact *pc)
{
    //打开文件
    FILE *pf = fopen("contact.dat", "rb");
    if (pf == NULL)
    {
        perror("loadContact::fopen");
        return;
    }

    //读文件
    PeoInfo tmp = { 0 };
    while (fread(&tmp, sizeof(PeoInfo), 1, pf)) //先放到临时变量里，因为通讯录可能已经满了
    {
        CheckCapacity(pc);
        pc -> data[pc -> sz] = tmp;
        pc -> sz++;
    }

    //关闭文件
    fclose(pf);
    pf = NULL;
}

//动态版本
void InitContact(Contact *pc)
{
    pc -> data = (PeoInfo *) malloc(DEFAULT_SZ * sizeof(PeoInfo));
    if (pc -> data == NULL)
    {
        printf("通讯录初始化失败：%s\n", strerror(errno));
        return;
    }
    pc -> sz = 0;
    pc -> capacity = DEFAULT_SZ;

    //加载文件的信息到通讯录中
    loadContact(pc);
}

static int FindByName(const Contact *pc, char name[]) //静态函数 - 只有在自己所在的 .c 文件才能使用，失去外部链接属性
{
    int pos = -1;
    for (int i = 0; i < pc -> sz; i++)
    {
        if (!strcmp(name, pc -> data[i].name))
        {
            pos = i;
            break;
        }
    }
    return pos;
}

int CheckCapacity(Contact *pc)
{
    if (pc -> sz == pc -> capacity)
    {
        PeoInfo *ptr = (PeoInfo *) realloc(pc, (pc->capacity + INC_SZ) * sizeof(PeoInfo));
        if (ptr == NULL)
        {
            printf("CheckCapacity:%s\n", strerror(errno));
            return 0;
        }
        else
        {
            pc->data = ptr;
            pc->capacity += INC_SZ;
            printf("增容成功，当前容量：%d\n", pc->capacity);
            return 1;
        }
    }
    return 1;
}

int CmpByName(const void *e1, const void *e2)
{
    return strcmp(((PeoInfo *) e1) -> name, ((PeoInfo *) e2) -> name);
}

//静态版本
/*
void AddContact(Contact *pc)
{
    if (pc -> sz == MAX)
    {
        printf("通讯录已满，无法增加\n");
        return;
    }
    printf("请输入名字:>");
    scanf("%s", (pc -> data)[pc -> sz].name);//有 sz 个，就把当前元素放到下标为 sz 空间中去
    printf("请输入年龄:>");
    scanf("%d", &(pc -> data)[pc -> sz].age);
    printf("请输入性别:>");
    scanf("%s", (pc -> data)[pc -> sz].sex);
    printf("请输入电话:>");
    scanf("%s", (pc -> data)[pc -> sz].tele);
    printf("请输入地址:>");
    scanf("%s", (pc -> data)[pc -> sz].addr);

    (pc -> sz)++;
    printf("添加成功\n");
}
*/

void AddContact(Contact *pc)
{
    CheckCapacity(pc);

    printf("请输入名字:>");
    scanf("%s", (pc -> data)[pc -> sz].name);//有 sz 个，就把当前元素放到下标为 sz 空间中去
    printf("请输入年龄:>");
    scanf("%d", &(pc -> data)[pc -> sz].age);
    printf("请输入性别:>");
    scanf("%s", (pc -> data)[pc -> sz].sex);
    printf("请输入电话:>");
    scanf("%s", (pc -> data)[pc -> sz].tele);
    printf("请输入地址:>");
    scanf("%s", (pc -> data)[pc -> sz].addr);

    (pc -> sz)++;
    printf("添加成功\n");
}

void ShowContact(const Contact *pc)
{
    //整齐美观 - 打印标题
    printf("%-12s %-7s %-8s %-14s %-30s\n", "姓名", "年龄", "性别", "电话", "地址");
    for (int i = 0; i < pc -> sz; i++)
    {
        printf("%-10s %-4d %-5s %-12s %-30s\n",
               pc -> data[i].name,
               pc -> data[i].age,
               pc -> data[i].sex,
               pc -> data[i].tele,
               pc -> data[i].addr);

    }
}

void DelContact(pContact pc)
{
    if (pc -> sz == 0)
    {
        printf("通讯录为空，无法删除\n");
        return;
    }
    //删除
    // 1.找到要删除的人(位置) - 下标
    printf("输入要删除的人的名字:>");
    char name[MAX_NAME] = { 0 };
    scanf("%s", name);
    int pos = FindByName(pc, name);

    if (pos < 0)
    {
        printf("名称不存在\n");
        return;
    }

    // 2.删除
    for (int i = pos; i < pc -> sz - 1; i++)
    {
        pc -> data[i] = pc -> data[i + 1];
    }
    pc -> sz--;
    printf("删除成功\n");
}

void SearchContact(const Contact *pc)
{
    char name[MAX_NAME] = { 0 };
    printf("请输入要查找的人的名字:>");
    scanf("%s", name);

    int pos = FindByName(pc, name);
    if (pos == -1)
    {
        printf("要查找的人不存在");
        return;
    }

    //打印
    printf("%-10s %-4s %-5s %-12s %-30s\n", "姓名", "年龄", "性别", "电话", "地址");
    printf("%-10s %-4d %-5s %-12s %-30s\n",
           pc -> data[pos].name,
           pc -> data[pos].age,
           pc -> data[pos].sex,
           pc -> data[pos].tele,
           pc -> data[pos].addr);
}

void ModifyContact(Contact *pc)
{
    char name[MAX_NAME] = { 0 };
    printf("请输入要修改的人的名字:>");
    scanf("%s", name);

    int pos = FindByName(pc, name);
    if (pos == -1)
    {
        printf("要查找的人不存在");
        return;
    }

    //修改
    printf("请输入名字:>");
    scanf("%s", (pc -> data)[pc -> sz].name);//有 sz 个，就把当前元素放到下标为 sz 空间中去
    printf("请输入年龄:>");
    scanf("%d", &(pc -> data)[pc -> sz].age);
    printf("请输入性别:>");
    scanf("%s", (pc -> data)[pc -> sz].sex);
    printf("请输入电话:>");
    scanf("%s", (pc -> data)[pc -> sz].tele);
    printf("请输入地址:>");
    scanf("%s", (pc -> data)[pc -> sz].addr);

    printf("修改成功\n");
}

void SortContact(Contact *pc)
{
    qsort(pc -> data, pc -> sz, sizeof(PeoInfo), CmpByName);
    printf("排序成功\n");
}

void DestroyContact(Contact *pc)
{
    free(pc -> data);
    pc -> data = NULL;
    pc -> sz = 0;
    pc -> capacity = 0;
    printf("释放内存 ...");
}

void saveContact(Contact *pc)
{
    FILE *pf = fopen("contact.dat", "wb");
    if (pf == NULL)
    {
        perror("saveContact::fopen");
        return;
    }

    for (int i = 0 ; i < pc -> sz; i++)
    {
        fwrite(pc -> data + i, sizeof(PeoInfo), 1, pf);
    }

    fclose(pf);
    pf = NULL;
    printf("保存成功 ...\n");
}